﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Windows.Forms;
using System.Runtime.Remoting.Messaging;
using TV_Agenda_V2.Objects;

namespace TV_Agenda_V2.Utilities
{
    class TVRageShowDataSource : IShowDataSource
    {
        public const String ShowSearchUrl = "http://www.tvrage.com/feeds/search.php?show={0}";
        public const String ShowInfoUrl = "http://www.tvrage.com/feeds/showinfo.php?sid={0}";
        public const String EpisodeInfoUrl = "http://www.tvrage.com/feeds/episode_list.php?sid={0}";


        public TVRageShowDataSource(Form parent) : base(parent)
        { }

        #region IShowDataSource members
        /// <summary>
        /// Searches for a show show.
        /// </summary>
        /// <param name="showName">Name of the show.</param>
        /// <returns>An XML Document with all the shows found by the search.</returns>
        public override List<Show> SearchShow(String showName)
        {
            XmlReader reader = new XmlTextReader(String.Format(ShowSearchUrl, showName));
            XmlDocument doc = new XmlDocument();
            doc.Load(reader);
            List<Show> results = ParseSearchResults(doc);
            return results;
        }

        /// <summary>
        /// Updates the show info.
        /// </summary>
        /// <param name="show">The show to update.</param>
        public override void UpdateShowInfo(Show show)
        {
            XmlReader reader = new XmlTextReader(String.Format(ShowInfoUrl, show.ID));
            XmlDocument doc = new XmlDocument();
            doc.Load(reader);
            ParseShowInfo(show, doc);
        }

        /// <summary>
        /// Updates the episodes of a show.
        /// </summary>
        /// <param name="show">The show.</param>
        public override void UpdateEpisodes(Show show)
        {
            String nextEpisodeString = show.NextEpisodeString;
            String prevEpisodeString = show.PreviousEpisodeString;

            XmlReader reader = new XmlTextReader(String.Format(EpisodeInfoUrl, show.ID));
            XmlDocument doc = new XmlDocument();
            doc.Load(reader);
            ParseEpisodes(show, doc);

            show.UpdateNextEpisode();
            show.UpdatePreviousEpisode();

            if (!nextEpisodeString.Equals(show.NextEpisodeString) && show.NextEpisode != null)
                show.NextEpisode.DisplayBold = true;
            else
                if (show.NextEpisode != null)
                    show.NextEpisode.DisplayBold = false;

            if (!prevEpisodeString.Equals(show.PreviousEpisodeString) && show.PreviousEpisode != null)
                show.PreviousEpisode.DisplayBold = true;
            else
                if (show.PreviousEpisode != null)
                    show.PreviousEpisode.DisplayBold = false;
        }

        /// <summary>
        /// Updates the shows.
        /// </summary>
        /// <param name="showList">The show list.</param>
        public override void UpdateShows(ShowList showList)
        {
            SetProgressMaximum(showList.Count);
            int counter = 1;
            foreach (Show show in showList)
            {
                SetProgress(counter);
                counter++;
                UpdateShowInfo(show);
                UpdateEpisodes(show);
            }
            CloseProgressDialog();
        }
        #endregion

        #region Private methods
        /// <summary>
        /// Parses the search results.
        /// </summary>
        /// <param name="doc">The xml document.</param>
        /// <returns>A list of shows.</returns>
        private List<Show> ParseSearchResults(XmlDocument doc)
        {
            List<Show> shows = new List<Show>();

            foreach (XmlNode node in doc.GetElementsByTagName("show"))
            {
                Show show = new Show();
                foreach (XmlElement element in node.ChildNodes)
                {
                    String name = element.Name.ToLower();
                    if (name.Equals("showid"))
                        show.ID = Int32.Parse(element.InnerText);
                    else if (name.Equals("name"))
                        show.Name = element.InnerText;
                    else if (name.Equals("link"))
                        show.Link = element.InnerText;
                    else if (name.Equals("country"))
                        show.Country = element.InnerText;
                    else if (name.Equals("started"))
                        show.Started = element.InnerText;
                    else if (name.Equals("ended"))
                        show.Ended = element.InnerText;
                    else if (name.Equals("seasons"))
                        show.NumberOfSeasons = Int32.Parse(element.InnerText ?? "-1");
                    else if (name.Equals("status"))
                        show.Status = element.InnerText;
                    else if (name.Equals("classification"))
                        show.Classification = element.InnerText;
                    else if (name.Equals("genres"))
                        foreach (XmlElement genre in element.ChildNodes)
                            show.Genres.Add(genre.InnerText);

                }
                shows.Add(show);
            }

            return shows;
        }

        /// <summary>
        /// Parses the show.
        /// </summary>
        /// <param name="show">The show to update.</param>
        /// <param name="document">The document to get data from.</param>
        private void ParseShowInfo(Show show, XmlDocument doc)
        {
            // TODO: Update a show by xml
            XmlElement root = doc.DocumentElement;
            foreach (XmlNode element in root.ChildNodes)
            {
                String name = element.Name.ToLower();
                if (name.Equals("showid"))
                    show.ID = Int32.Parse(element.InnerText);
                else if (name.Equals("showname"))
                    show.Name = element.InnerText;
                else if (name.Equals("showlink"))
                    show.Link = element.InnerText;
                else if (name.Equals("origin_country"))
                    show.Country = element.InnerText;
                else if (name.Equals("status"))
                    show.Status = element.InnerText;
                else if (name.Equals("classification"))
                    show.Classification = element.InnerText;
                else if (name.Equals("genres"))
                {
                    show.Genres.Clear();
                    foreach (XmlElement genre in element.ChildNodes)
                        show.Genres.Add(genre.InnerText);
                }
                else if (name.Equals("runtime"))
                    show.Runtime = Int32.Parse(element.InnerText ?? "-1");
                else if (name.Equals("network"))
                {
                    show.Network = element.InnerText;
                    show.NetworkCountry = element.Attributes["country"].InnerText;
                }
                else if (name.Equals("airtime"))
                    show.AirTime = element.InnerText;
                else if (name.Equals("airday"))
                    show.AirDay = element.InnerText;
                else if (name.Equals("timezone"))
                    show.Timezone = element.InnerText;
                else if (name.Equals("akas"))
                {
                    show.Akas.Clear();
                    foreach (XmlElement aka in element.ChildNodes)
                    {
                        Aka a = new Aka();
                        a.Name = aka.InnerText;

                        if (aka.Attributes["country"] != null)
                            a.Country = aka.Attributes["country"].InnerText;

                        if (aka.Attributes["attr"] != null)
                            a.Attr = aka.Attributes["attr"].InnerText;

                        show.Akas.Add(a);
                    }

                }
            }
        }

        /// <summary>
        /// Parses the episodes from XML.
        /// </summary>
        /// <param name="show">The Show.</param>
        /// <param name="doc">The XmlDocument.</param>
        private void ParseEpisodes(Show show, XmlDocument doc)
        {
            XmlElement docElement = doc.DocumentElement;
            foreach (XmlNode node in docElement.ChildNodes)
            {
                String name = node.Name.ToLower();
                if (name.Equals("totalseasons"))
                    show.NumberOfSeasons = Int32.Parse(node.InnerText ?? "-1");
                else if (name.Equals("episodelist"))
                {
                    show.Seasons.Clear();
                    foreach (XmlNode seasonList in node.ChildNodes)
                    {
                        String name2 = seasonList.Name.ToLower();
                        if (name2.Equals("season"))
                        {
                            Season season = new Season();
                            if (seasonList.Attributes["no"] != null)
                                season.Number = Int32.Parse(seasonList.Attributes["no"].InnerText ?? "-1");
                            foreach (XmlNode episodeList in seasonList.ChildNodes)
                            {
                                String name3 = episodeList.Name.ToLower();
                                if (name3.Equals("episode"))
                                {
                                    Episode e = new Episode();
                                    e.SeasonNumber = season.Number;
                                    foreach (XmlNode episode in episodeList.ChildNodes)
                                    {
                                        String name4 = episode.Name.ToLower();
                                        if (name4.Equals("epnum"))
                                            e.EpisodeNumber = Int32.Parse(String.IsNullOrEmpty(episode.InnerText) ? "-1" : episode.InnerText);
                                        else if (name4.Equals("seasonnum"))
                                            e.SeasonEpisodeNumber = Int32.Parse(String.IsNullOrEmpty(episode.InnerText) ? "-1" : episode.InnerText);
                                        else if (name4.Equals("prodnum"))
                                            e.ProdNumber = episode.InnerText;
                                        else if (name4.Equals("airdate"))
                                            e.AirDate = episode.InnerText;
                                        else if (name4.Equals("link"))
                                            e.Link = episode.InnerText;
                                        else if (name4.Equals("title"))
                                            e.Title = episode.InnerText;
                                    }
                                    season.Episodes.Add(e);
                                }
                            }
                            show.Seasons.Add(season);
                        }

                    }
                }
            }
        }
        
        #endregion
    }
}
